package com.duojuhe.common.utils.jwt;

import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * jwt操作工具类
 **/
public class JwtUtils {
    //密钥，动态生成的密钥
   // private static final SecretKey KEY = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    //主题
    private static final String SUBJECT = "duoHuHe";
    //发送方
    private static final String ISSUER = "duojuhe.com";

    /**
     * 生成加密后的秘钥字符串
     * @return
     */
    public static String secretKeyToSecretString() {
        //创建一个签名密钥，通常在配置文件中设置
        SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
        return Base64.getEncoder().encodeToString(key.getEncoded());
    }

    /**
     * 秘钥字符串转成SecretKey
     * @return
     */
    public static SecretKey secretStringToSecretKey(String encodedKey) {
        // decode the base64 encoded string
        byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
        return new SecretKeySpec(decodedKey, 0, decodedKey.length, "HmacSHA256");
    }

    /**
     * 获取一个key
     * @return
     */
    private static SecretKey generalKey(){
        return secretStringToSecretKey("ekKY8u+LmGzVstR7aUtaS/W1pBrjuCAni4U6mlOHVnI=");
    }

    /**
     * 生成token
     *
     * @param claims
     * @param expireMinute
     * @return
     */
    public static String generate(Map<String, Object> claims, long expireMinute) {
        //过期时间
        long expire = expireMinute * 60 * 1000;
        //当前时间
        Date nowDate = new Date();
        //过期时间,设定
        Date expireDate = new Date(System.currentTimeMillis() + expire);
        //头部信息,可有可无
        Map<String, Object> header = new HashMap<>(2);
        header.put("typ", SUBJECT);
        //更强的密钥,JDK11起才能用
        //KeyPair keyPair = Keys.keyPairFor(SignatureAlgorithm.RS256);
        //PrivateKey key1 =  keyPair.getPrivate();  // 私钥
        //PublicKey key2 =  keyPair.getPublic();  //公钥
        return Jwts.builder().setHeader(header)
                .setSubject(SUBJECT)//主题
                .setIssuer(ISSUER) //发送方
                .setClaims(claims)  //自定义claims
                .setIssuedAt(nowDate)//当前时间
                .setExpiration(expireDate) //过期时间
                .signWith(generalKey())//签名算法和key
                .compact();
    }

    /**
     * 生成token
     *
     * @param header 传入头部信息map
     * @param claims 要传送消息map
     * @return
     */
    public static String generate(Map<String, Object> header, Map<String, Object> claims, long expireMinute) {
        //过期时间
        long expire = expireMinute * 60 * 1000;
        //当前时间
        Date nowDate = new Date();
        //过期时间,设定
        Date expireDate = new Date(System.currentTimeMillis() + expire);
        return Jwts.builder().setHeader(header)
                .setSubject(SUBJECT)//主题
                .setIssuer(ISSUER) //发送方
                .setClaims(claims)  //自定义claims
                .setIssuedAt(nowDate)//当前时间
                .setExpiration(expireDate) //过期时间
                .signWith(generalKey())//签名算法和key
                .compact();
    }

    /**
     * 校验是不是jwt签名
     *
     * @param token
     * @return
     */
    public static boolean isSigned(String token) {
        return Jwts.parserBuilder().setSigningKey(generalKey()).build().isSigned(token);
    }

    /**
     * 校验签名是否正确
     *
     * @param token
     * @return
     */
    public static boolean verify(String token) {
        try {
            Jwts.parserBuilder().setSigningKey(generalKey()).build().parseClaimsJws(token);
            return true;
        } catch (JwtException e) {
            return false;
        }
    }

    /**
     * 获取payload 部分内容（即要传的信息）
     * 使用方法：如获取userId：getClaim(token).get("userId");
     *
     * @param token
     * @return
     */
    public static Claims getClaim(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parserBuilder().setSigningKey(generalKey()).build().parseClaimsJws(token).getBody();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return claims;
    }

    /**
     * 获取头部信息map
     * 使用方法 : getHeader(token).get("alg");
     *
     * @param token
     * @return
     */
    public static JwsHeader getHeader(String token) {
        JwsHeader header = null;
        try {
            header = Jwts.parserBuilder().setSigningKey(generalKey()).build().parseClaimsJws(token).getHeader();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return header;
    }

    /**
     * 获取jwt发布时间
     */
    public static Date getIssuedAt(String token) {
        return getClaim(token).getIssuedAt();
    }

    /**
     * 获取jwt失效时间
     */
    public static Date getExpiration(String token) {
        return getClaim(token).getExpiration();
    }

    /**
     * 验证token是否失效
     *
     * @param token
     * @return true:过期   false:没过期
     */
    public static boolean isExpired(String token) {
        try {
            final Date expiration = getExpiration(token);
            return expiration.before(new Date());
        } catch (Exception e) {
            return true;
        }
    }

    /**
     * 直接Base64解密获取header内容
     *
     * @param token
     * @return
     */
    public static String getHeaderByBase64(String token) {
        String header = null;
        if (isSigned(token)) {
            try {
                byte[] header_byte = Base64.getDecoder().decode(token.split("\\.")[0]);
                header = new String(header_byte);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        return header;
    }

    /**
     * 直接Base64解密获取payload内容
     *
     * @param token
     * @return
     */
    public static String getPayloadByBase64(String token) {
        String payload = null;
        if (isSigned(token)) {
            try {
                byte[] payload_byte = Base64.getDecoder().decode(token.split("\\.")[1]);
                payload = new String(payload_byte);
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        return payload;
    }

    public static void main(String[] args) {
        //用户自定义信息claims
        Map<String, Object> map = new HashMap<>();
        map.put("userId", "test122");
        String token = generate(map, 30);
        System.out.println(token);

        System.out.println("claim:" + getClaim(token).get("userId"));
        System.out.println("header:" + getHeader(token));
        //    System.out.println(getIssuedAt(token));
        Claims claims = getClaim(token);

        //  System.out.println(getHeaderByBase64(token));
        System.out.println(getPayloadByBase64(token));

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy‐MM‐dd hh:mm:ss");
        System.out.println("签发时间:" + sdf.format(claims.getIssuedAt()));
        System.out.println("过期时间:" + sdf.format(claims.getExpiration()));
        System.out.println("当前时间:" + sdf.format(new Date()));
        System.out.println("是否有效:" + verify("eyJ0eXAiOiJkdW9IdUhlIiwiYWxnIjoiSFMyNTYifQ.eyJ1c2VySWQiOiJ0ZXN0MTIyIiwiaWF0IjoxNjY5ODYxMDUxLCJleHAiOjE2Njk4NjExMTF9.X7TsA3TQBD2OZV28Q79btgrJIGvhbPI7k91Cw4R3EcY"));
    }
}


